/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls;

import com.inspur.edp.cef.api.repository.GspDbDataType;
import com.inspur.edp.cef.entity.entity.FieldType;
import com.inspur.edp.cef.spi.entity.PropertyDefaultValue;
import com.inspur.edp.cef.spi.entity.info.CefDataTypeInfo;
import com.inspur.edp.cef.spi.entity.info.EnumValueInfo;
import com.inspur.edp.cef.spi.entity.info.UniqueConstraintInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.AssocationPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.BasePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ComplexUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.DataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.EnumPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ObjectType;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.SimpleAssoUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.EntityResInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.ValueObjResInfo;
import com.inspur.edp.cef.spi.jsonser.entity.AbstractEntitySerializerItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class CefValueObjResInfo extends ValueObjResInfo {

  private final String entityCode;
  private final String displayValueKey;
  private  CefValueObjModelResInfo modelResInfo;
  CefDataTypeInfo dataTypeInfo;
  private volatile ArrayList<String> propertyNames;

  /**
   * 运行时获取propertyNames
   *
   * @return propertyName集合
   */
  public ArrayList<String> getPropertyNames() {
    ArrayList<String> propertyNamesTemp;
    if (propertyNames == null) {
      propertyNamesTemp = new ArrayList<>();
      if (dataTypeInfo != null) {
        propertyNamesTemp.addAll(dataTypeInfo.getPropertyInfos().keySet());
        propertyNamesTemp.removeAll(Collections.singleton(null));
      }
      propertyNames = propertyNamesTemp;
    }
    return propertyNames;
  }

  public  CefValueObjResInfo(String entityCode,String displayValueKey)
{
  this.entityCode = entityCode;
  this.displayValueKey = displayValueKey;
  dataTypeInfo=new CefDataTypeInfo(displayValueKey);
  initColumns();
}

  protected void initColumns()
  {}

  protected final void addPropertyInfo(DataTypePropertyInfo propertyInfo)
  {
    dataTypeInfo.getPropertyInfos().put(propertyInfo.getPropertyName(),propertyInfo);
  }

  public String getEntityCode() {
    return entityCode;
  }


  @Override
  public final String getDisplayName() {
    return modelResInfo.getResourceItemValue(dataTypeInfo.getDisplayValueKey());
  }

  @Override
  public String getPropertyDispalyName(String labelId) {
    return modelResInfo.getResourceItemValue( dataTypeInfo.getPropertyInfos().get(labelId).getDisplayValueKey());
  }

  @Override
  public String getEnumPropertyDispalyValue(String labelId, String enumKey) {
    DataTypePropertyInfo info = dataTypeInfo.getPropertyInfos().get(labelId);
    if(info.getObjectType() == ObjectType.Enum){
      return modelResInfo.getResourceItemValue(((EnumPropertyInfo)info.getObjectInfo()).getEnumValueInfo(enumKey)
          .getDisplayValueKey());
    }
    throw new RuntimeException("当前属性"+labelId+"不是枚举类型，无法获取枚举值");
  }

  @Override
  public EnumValueInfo getPropEnumInfo(String labelId, String enumKey) {
    DataTypePropertyInfo info = dataTypeInfo.getPropertyInfos().get(labelId);
    if(info.getObjectType() == ObjectType.Enum){
      return ((EnumPropertyInfo)info.getObjectInfo()).getEnumValueInfo(enumKey);
    }
    throw new RuntimeException("当前属性"+labelId+"不是枚举类型，无法获取枚举值");

  }

  @Override
  public List<EnumValueInfo> getPropEnumInfos(String labelId) {
    DataTypePropertyInfo info = dataTypeInfo.getPropertyInfos().get(labelId);
    if(info.getObjectType() == ObjectType.Enum){
      return ((EnumPropertyInfo)info.getObjectInfo()).getEnumValueInfos();
    }
    throw new RuntimeException("当前属性"+labelId+"不是枚举类型，无法获取枚举值");
  }

  @Override
  public String getAssoRefPropertyDisplay(String labelId, String refEleCode) {
    return super.getAssoRefPropertyDisplay(labelId, refEleCode);
  }

  public List<AbstractEntitySerializerItem> getChangeDeserialzers()
  {
    throw new UnsupportedOperationException();
  }

  public CefDataTypeInfo getEntityTypeInfo()
  {return dataTypeInfo;}

   void setModelResInfo(
      CefValueObjModelResInfo modelResInfo) {
    this.modelResInfo = modelResInfo;
  }

  public final String getI18nPrefix() {
    String displayValueKey = dataTypeInfo.getDisplayValueKey();
    return displayValueKey.substring(0, displayValueKey.length()-6);
  }


  protected DataTypePropertyInfo addPropertyInfo(String propertyName, String displayValueKey,
      boolean required, boolean enableRtrim, int length, int pricision,
      FieldType fieldType, ObjectType objectType, PropertyDefaultValue defaultValue,
      boolean defaultNull, boolean isMulti,
      BasePropertyInfo basePropertyInfo) {
    DataTypePropertyInfo dataTypePropertyInfo = createDataTypePropertyInfo(propertyName,
        displayValueKey, required, enableRtrim, length, pricision,
        fieldType, objectType, defaultValue, isMulti, defaultNull, null, null,
        basePropertyInfo);
    addPropertyInfo(dataTypePropertyInfo);
    return dataTypePropertyInfo;
  }

  protected DataTypePropertyInfo addStringPropertyInfo(String propertyName, boolean required,
      boolean enableRtrim, int length) {
    return addStringPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, enableRtrim, length, null, false, false);
  }

  protected DataTypePropertyInfo addStringPropertyInfo(String propertyName,
      String displayValueKey, boolean required, boolean enableRtrim, int length,
      PropertyDefaultValue defaultValue, boolean defaultNull, boolean isMulti) {
    return addPropertyInfo(propertyName, displayValueKey, required, enableRtrim, length, 0,
        FieldType.String, ObjectType.Normal, defaultValue, defaultNull, isMulti, null);
  }

  protected DataTypePropertyInfo addTextPropertyInfo(String propertyName, boolean required,
      boolean enableRtrim) {
    return addTextPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required,
        enableRtrim, null, false, false);
  }

  protected DataTypePropertyInfo addTextPropertyInfo(String propertyNme, String displayValueKey,
      boolean requried, boolean enableRtrim, PropertyDefaultValue defaultValue,
      boolean isDefaultNull,
      boolean isMulti) {
    return addPropertyInfo(propertyNme, displayValueKey, requried, enableRtrim, 0, 0,
        FieldType.Text, ObjectType.Normal, defaultValue, isDefaultNull, isMulti, null);
  }


  protected DataTypePropertyInfo addDatePropertyInfo(String propertyName, boolean required) {
    return addDatePropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, null, false);
  }

  protected DataTypePropertyInfo addDatePropertyInfo(String propertyName, String displayValueKey,
      boolean required, PropertyDefaultValue defaultValue
      , boolean defaultNull) {
    return addPropertyInfo(propertyName, displayValueKey, required, false, 0, 0, FieldType.Date,
        ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected DataTypePropertyInfo addDateTimePropertyInfo(String propertyName, boolean required) {
    return addDateTimePropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, null, false);
  }

  protected DataTypePropertyInfo addDateTimePropertyInfo(String propertyName,
      String displayValueKey, boolean required, PropertyDefaultValue defaultValue,
      boolean defaultNull) {
    return addPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
        FieldType.DateTime, ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected DataTypePropertyInfo addIntPropertyInfo(String propertyName, boolean required) {
    return addIntPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, null, false);
  }

  protected DataTypePropertyInfo addIntPropertyInfo(String propertyName, String displayValueKey,
      boolean required, PropertyDefaultValue defaultValue,
      boolean defaultNull) {
    return addPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
        FieldType.Integer, ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected DataTypePropertyInfo addDecimalPropertyInfo(String propertyName, boolean requried,
      int length, int pricision) {
    return addDecimalPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        requried, length, pricision, null, false);
  }

  protected DataTypePropertyInfo addDecimalPropertyInfo(String propertyName,
      String propertyDispalyKey, boolean requried, int length, int pricision,
      PropertyDefaultValue defaultValue, boolean defaultNull) {
    return addPropertyInfo(propertyName, propertyDispalyKey, requried, false, length, pricision,
        FieldType.Decimal, ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected DataTypePropertyInfo addBooleanPropertyInfo(String propertyName, boolean requried) {
    return addBooleanPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        requried, null, false);
  }

  protected DataTypePropertyInfo addBooleanPropertyInfo(String propertyName,
      String propertyDisplayValue, boolean required, PropertyDefaultValue defaultValue,
      boolean defaultNull) {
    return addPropertyInfo(propertyName, propertyDisplayValue, required, false, 0, 0,
        FieldType.Boolean, ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected String getFieldPropertyDisplayValue(String propertyName) {
    return getDisplayPrefix() + "." + propertyName + ".Name";
  }

  protected DataTypePropertyInfo addBytesPropertyInfo(String propertyName, boolean required) {
    return addBytesPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, null, false);
  }

  protected DataTypePropertyInfo addBytesPropertyInfo(String propertyName, String displayValueKey,
      boolean required, PropertyDefaultValue defaultValue,
      boolean defaultNull) {
    return addPropertyInfo(propertyName, displayValueKey, required, false, 0, 0,
        FieldType.Binary, ObjectType.Normal, defaultValue, defaultNull, false, null);
  }

  protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName, boolean required,
      boolean enableRtrim,
      AssocationPropertyInfo associationInfo) {
    return addAssociationProperyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        required, enableRtrim, 36, false, associationInfo);
  }

  protected final DataTypePropertyInfo addAssociationProperyInfo(String propertyName,
      String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
      boolean isDefaultNull, AssocationPropertyInfo associationInfo) {
    return addPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0,
        FieldType.String, ObjectType.Association, null, isDefaultNull, false,  associationInfo);
  }

  protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName, boolean requried,
      boolean enableRtrim,  SimpleAssoUdtPropertyInfo associationInfo) {
    return addAssoUdtPropertyInfo(propertyName, getFieldPropertyDisplayValue(propertyName),
        requried, enableRtrim, 36, false,associationInfo);
  }

  protected final DataTypePropertyInfo addAssoUdtPropertyInfo(String propertyName,
      String propertyDisplayKey, boolean required, boolean enableRtrim, int length,
      boolean isDefaultNull, SimpleAssoUdtPropertyInfo associationInfo) {
    return addPropertyInfo(propertyName, propertyDisplayKey, required, enableRtrim, length, 0,
        FieldType.Udt, ObjectType.Association, null, isDefaultNull, false,associationInfo);
  }
  protected final String getDisplayPrefix() {
    return getDisplayName().substring(0, getDisplayName().lastIndexOf("."));
  }

  protected  final DataTypePropertyInfo addComplexUdtPropertyInfo(String propertyName,
      ComplexUdtPropertyInfo udtPropertyInfo)
  {
    return addComplexUdtPropertyInfo(propertyName,getDisplayPrefix(),udtPropertyInfo);
  }

  protected  final DataTypePropertyInfo addComplexUdtPropertyInfo(String propertyName,String propertyDisplayValueKey,
      ComplexUdtPropertyInfo udtPropertyInfo)
  {
    return addPropertyInfo(propertyName, propertyDisplayValueKey, false, false, 0, 0,
        FieldType.Udt, ObjectType.UDT, null, false, false, udtPropertyInfo);
  }

  protected DataTypePropertyInfo createDataTypePropertyInfo(String propertyName,
      String displayValueKey, boolean required, boolean enableRtrim, int length,
      int precision, FieldType fieldType, ObjectType objectType, PropertyDefaultValue defaultValue,
      boolean isMulti, boolean defaultNull,GspDbDataType dbDataType,String dbColumnName,
      BasePropertyInfo basePropertyInfo) {
    DataTypePropertyInfo befPropertyInfo=new DataTypePropertyInfo(propertyName,displayValueKey,required,enableRtrim,length,precision,fieldType,objectType,basePropertyInfo,defaultValue,isMulti,defaultNull);
    befPropertyInfo.setDbDataType(dbDataType);
    befPropertyInfo.setDbColumnName(dbColumnName);
    return befPropertyInfo;
  }
}
